use std::{sync::Arc, ops::DerefMut};
use tonic::{Status, Response};

use crate::gen::{mini_mulazim::{restaurant_service_server::RestaurantService}, entities::{Restaurant, Address, Contact, MetaData, Food, Name}};
use super::{data_container::DataContainer, exts::{IntoTonicResponse, ToKeysResponse, ToOption, OptionToResult, Apply, GetEntityKey}};

/**
 * @author Dream-Lab مۇختەرجان مەخمۇت
 * @email ug-project@outlook.com
 * @create date 2022-07-24 21:40:26
 * @modify date 2022-07-24 21:40:26
 * @desc [description]
*/


pub struct RestaurantServiceImpl {
    pub data: Arc<DataContainer>
}

#[async_trait::async_trait]
impl RestaurantService for RestaurantServiceImpl {
    async fn create(&self,request:tonic::Request<crate::gen::mini_mulazim::CreateRestaurantRequest> ,) ->  Result<tonic::Response<crate::gen::entities::Restaurant> ,tonic::Status> {
        let request = request.into_inner();
        self.data.get_user_by_id(&request.owner_id).into_result(Status::not_found("owner not found"))?;
        {
            let restaurant = self.data.insert_restaurant(Restaurant {
                owner: None,
                owner_id: request.owner_id,
                address: Address::default().into(),
                contact: Contact::default().into(),
                meta: MetaData::new_with_default_value().into(),
                foods: vec![
                    Food { name: Name { ug: "لەغمەن".into(), zh: "拉面".into(), meta: MetaData::new_with_default_value().into() }.into(), price: 22.5f32, meta: MetaData::new_with_default_value().into() },
                    Food { name: Name { ug: "پولۇ".into(), zh: "抓饭".into(), meta: MetaData::new_with_default_value().into() }.into(), price: 30.5f32, meta: MetaData::new_with_default_value().into() },
                    Food { name: Name { ug: "سامسا".into(), zh: "肉囊".into(), meta: MetaData::new_with_default_value().into() }.into(), price: 3.5f32, meta: MetaData::new_with_default_value().into() },
                    Food { name: Name { ug: "سۇيۇقئاش".into(), zh: "烫面".into(), meta: MetaData::new_with_default_value().into() }.into(), price: 20.5f32, meta: MetaData::new_with_default_value().into() },
                    Food { name: Name { ug: "كاۋاپ".into(), zh: "烤肉".into(), meta: MetaData::new_with_default_value().into() }.into(), price: 7.5f32, meta: MetaData::new_with_default_value().into() },
                    Food { name: Name { ug: "ئەتكەن چاي".into(), zh: "茶".into(), meta: MetaData::new_with_default_value().into() }.into(), price: 5.5f32, meta: MetaData::new_with_default_value().into() },
                ]
            });
            restaurant
        }.into_option().into_tonic_response()
    }

    async fn update(&self,request:tonic::Request<crate::gen::entities::Restaurant> ) ->  Result<tonic::Response<crate::gen::entities::Restaurant> ,tonic::Status> {
        self.data.update_restaurant(request.into_inner()).into_option().into_tonic_response()
    }

    async fn get_by_id(&self,request:tonic::Request<crate::gen::mini_mulazim::Id> ,) ->  Result<tonic::Response<crate::gen::entities::Restaurant> ,tonic::Status> {
        self.data.get_restaurant_by_id(&request.into_inner().uuid).apply(|me|{
            if let Some(ref mut me) = me {
                me.owner = self.data.get_user_by_id(&me.owner_id)
            }
        }).into_tonic_response()
    }

    async fn list(&self,request:tonic::Request<crate::gen::mini_mulazim::KeysRequest> ,) ->  Result<tonic::Response<crate::gen::mini_mulazim::KeysResponse> ,tonic::Status> {
        self.data.get_keys_of(&self.data.restaurants, &request.into_inner()).into_keys_response().into_option().into_tonic_response()
    }
}
